/**
* Class providing basic datagrid functionality
* @class DataGrid
* @inherits minjs.Table 
*/
/**
* Creates the DataGrid object
* @constructor DataGrid
*/
minjs.DataGrid = function() {

	minjs.Table.call(this);
	
	var _recordFilter = minjs.DataGrid.RecordFilter.NoDeletedRecords;
	var _rowFormatter = minjs.DataGrid.RowFormatter.createOddEvenRowFormatter();
	var _fields = [];

	this.setRecordFilter = function(recordFilter){_recordFilter = recordFilter;}
	this._getRecordFilter = function(){return _recordFilter;}
	this.setRowFormatter = function(rowFormatter){_rowFormatter = rowFormatter;}
	this._getRowFormatter = function(){return _rowFormatter;}
	this._getFields = function(){return _fields;}
}

minjs.DataGrid.prototype = new minjs.Table();
minjs.DataGrid.prototype.constructor = minjs.DataGrid;

/**
* Adds a data-bound field (i.e. column) to the grid
* @function {void} addField
* @param {String} name - visual name of the field
* @param {optional String} mapping - name of the field of the data row that this field will be mapped to (if not given the 'name' parameter will be used instead)
*/
minjs.DataGrid.prototype.addField = function(field){
	this._getFields().push(field);	// TODO: assert field is instanceof DataGrid.Field ???
}

minjs.DataGrid.prototype.getFieldCount = function(){
	return this._getFields().length;
}

minjs.DataGrid.prototype.getField = function(index){
	return this._getFields()[index];
}

/**
* 
* @function {void} renderDataSet
*/
minjs.DataGrid.prototype.renderDataSet = function(dataset){
	
	//this.setInnerHTML(""); // clear all rows, header and footer, if present
	
	var fieldCount = this.getFieldCount();	// TODO: optimize for the case of 0 fields ???
	{
		var row = this.insertHeaderRow(0);
		for(var i = 0; i < fieldCount; i++){
			var field = this.getField(i);
			var cell = row.insertCell(i);
			field.renderHeaderCell(cell);
		}
	}			
	
	for(var i = 0; i < dataset.getRecordCount(); i++){
		var record = dataset.getRecord(i);
		var recordFilter = this._getRecordFilter();
		if(!recordFilter || recordFilter(record)){			
			var row = this.insertRow(i);
			this._getRowFormatter() && this._getRowFormatter().onNextRow(row);
			for(var j = 0; j < fieldCount; j++){
				var field = this.getField(j);
				var cell = row.insertCell(j);
				//var value = record.getValue(dataset.getField(j).getName());
				var value = record.getValue(field.getMapping());
				field.renderCell(cell, value);
			}
		}
	}	
	
	{
		var row = this.insertFooterRow(0);
		for(var i = 0; i < fieldCount; i++){
			var field = this.getField(i);
			var cell = row.insertCell(i);
			field.renderFooterCell(cell);
		}
	}
}

/*minjs.DataGrid.prototype.onCellValueChanged = function(fieldIndex, cellIndex){
	var field = this._getFields()[fieldIndex];
	var columnSummary = field.getColumnSummary();
	if(columnSummary){
		columnSummary.reset();
		for(var i = 0; i < this.getRowCount(); i++){
			columnSummary.onNextValue(
}
*/
/*DataGrid.prototype.onloading = function(){
	mask(this.getElement(), true, "Loading...");
}

DataGrid.prototype.onloaded = function(){
	mask(this.getElement(), false);
	this.update();
}

DataGrid.prototype.onfailed = function(status, error_text){
	mask(this.getElement(), false);
	alert("Loading data failed\nStatus: " + status + "\nError: " + (error_text || ""));
}
*/

/**
* @class minjs.DataGrid.Field
*/
minjs.DataGrid.Field = function(name, mapping/*, cellRenderer, headerRenderer, footerRenderer, columnSummary*/){
	this.getName = function(){return name;}
	this.getMapping = function(){return mapping;}
	//this.getCellRenderer = function(){return cellRenderer;}
	//this.getHeaderRenderer = function(){return headerRenderer;}
	//this.getFooterRenderer = function(){return footerRenderer;}
	//this.getColumnSummary = function(){return columnSummary;}
}

minjs.DataGrid.Field.prototype.renderCell = function(cell, value){
	//var cellRenderer = this.getCellRenderer();
	//var columnSummary = this.getColumnSummary();
	//cellRenderer && cellRenderer(cell, value);
	//columnSummary && columnSummary.onNextValue(value);
	
	cell.setInnerHTML(value);
	//columnSummary && columnSummary.onNextValue(value);
}

minjs.DataGrid.Field.prototype.renderHeaderCell = function(cell){
	cell.setInnerHTML(this.getName());
}

minjs.DataGrid.Field.prototype.renderFooterCell = function(cell){
	/* DO NOTHING */
}

/**
* @class minjs.DataGrid.NumberField
*/
minjs.DataGrid.NumberField = function(name, mapping, format, columnSummary){
	minjs.DataGrid.Field.call(this, name, mapping);
	this.getFormat = function(){return format;}
	this.getColumnSummary = function(){return columnSummary;}
}

minjs.DataGrid.NumberField.prototype = new minjs.DataGrid.Field();
minjs.DataGrid.NumberField.prototype.constructor = minjs.DataGrid.NumberField;

minjs.DataGrid.NumberField.prototype.renderCell = function(cell, value){
	var format = this.getFormat();
	var str = (new minjs.Number(value)).toString(format);
	cell.setInnerHTML(str);
	var columnSummary = this.getColumnSummary();
	columnSummary && columnSummary.onNextValue(value);	
}

minjs.DataGrid.NumberField.prototype.renderFooterCell = function(cell){
	var columnSummary = this.getColumnSummary();
	columnSummary && cell.setInnerHTML(columnSummary.getResult());
}

/**
* @class minjs.DataGrid.DateField
*/
minjs.DataGrid.DateField = function(name, mapping, format){
	minjs.DataGrid.Field.call(this, name, mapping);
	this.getFormat = function(){return format;}
}

minjs.DataGrid.DateField.prototype = new minjs.DataGrid.Field();
minjs.DataGrid.DateField.prototype.constructor = minjs.DataGrid.DateField;

minjs.DataGrid.DateField.prototype.renderCell = function(cell, value){
	var format = this.getFormat();
	//var str = format ? value.toLocaleDateString() : value.toLocaleDateString(); // TODO: fix it !!!
	var str = (new minjs.Date(value)).toString(format);
	cell.setInnerHTML(str);
}

/**
* @class minjs.DataGrid.ImageField
*/
minjs.DataGrid.ImageField = function(name, mapping, width, height){
	minjs.DataGrid.Field.call(this, name, mapping);
	this.getWidth = function(){return width;}
	this.getHeight = function(){return height;}
}

minjs.DataGrid.ImageField.prototype = new minjs.DataGrid.Field();
minjs.DataGrid.ImageField.prototype.constructor = minjs.DataGrid.ImageField;

minjs.DataGrid.ImageField.prototype.renderCell = function(cell, value){
	if(value){
		var width = this.getWidth();
		var height = this.getHeight();
		var img = minjs.Element.create("img");
		img.setAttribute("src", value);
		width && img.setAttribute("width", width);
		height && img.setAttribute("height", height);
		cell.add(img);
	}
}

/**
* @class minjs.DataGrid.EditableField
*/
minjs.DataGrid.EditableField = function(name, mapping){
	minjs.DataGrid.Field.call(this, name, mapping);
}

minjs.DataGrid.EditableField.prototype = new minjs.DataGrid.Field();
minjs.DataGrid.EditableField.prototype.constructor = minjs.DataGrid.EditableField;

minjs.DataGrid.EditableField.prototype.renderCell = function(cell, value){
	
	function onClick(){
		input.getDOMElement().readOnly = false;
	}
	
	function onBlur(){
		input.getDOMElement().readOnly = true;
		input.getDOMElement().value = input.getDOMElement().value;
	}
	
	var input = minjs.Element.create("input");
	input.setAttribute("type", "text");
	input.setClassName("minjs-DataGrid-EditableField");
	input.setValue(value);
	input.addEventListener("click", onClick);
	input.addEventListener("blur", onBlur);
	cell.add(input);
}

/**
* @class minjs.DataGrid.EditableNumberField
*/
minjs.DataGrid.EditableNumberField = function(name, mapping, columnSummary){
	minjs.DataGrid.NumberField.call(this, name, mapping, columnSummary);
}

minjs.DataGrid.EditableNumberField.prototype = new minjs.DataGrid.NumberField();
minjs.DataGrid.EditableNumberField.prototype.constructor = minjs.DataGrid.EditableNumberField;

minjs.DataGrid.EditableNumberField.prototype.renderCell = function(cell, value){
	var columnSummary = this.getColumnSummary();
	
	function onClick(){
		input.getDOMElement().readOnly = false;
	}
	
	function onBlur(){
		input.getDOMElement().readOnly = true;
		input.setValue(input.getValue());
	}
	
	function onKeyPress(e){
		var keynum = window.minjs ? e.keyCode : e.charCode;
		var keychar = String.fromCharCode(keynum);
		var numcheck = /\d/;
		if(!numcheck.test(keychar))
			e.preventDefault ? e.preventDefault() : e.returnValue = false;
	}
	
	var input = minjs.Element.create("input");
	input.setAttribute("type", "text");
	input.setClassName("minjs-DataGrid-EditableField");
	input.addClassName("minjs-DataGrid-EditableNumberField");
	input.setValue(value);
	input.addEventListener("click", onClick);
	input.addEventListener("blur", onBlur);
	input.addEventListener("keypress", onKeyPress);
	cell.add(input);
	
	columnSummary && columnSummary.onNextValue(value);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
minjs.DataGrid.RecordFilter = {
	NoDeletedRecords: function(record){
		return record.getState() != minjs.DataSet.Record.State.DELETED;
	}
};

minjs.DataGrid.RowFormatter = {
	createOddEvenRowFormatter: function(){
		function a (el, cn){
			return function(){
				el.addClassName(cn);
			}
		}		
		function b (el, cn){
			return function(){
				el.removeClassName(cn);
			}
		}
		return {
			rownum: 0,
			onNextRow: function(row){
				row.setClassName((++this.rownum % 2) ? "minjs-Table-oddRow" : "minjs-Table-evenRow");
				row.addEventListener("mouseover", a(row, "minjs-Table-rowMouseover"));
				row.addEventListener("mouseout", b(row, "minjs-Table-rowMouseover"));
			}
		}
	}
};

minjs.DataGrid.ColumnSummary = {
	createTotalSum: function(){
		var result = 0;
		return {
			reset: function(){
				result = 0;
			},
			onNextValue:function(value){
				result += value;
			},
			getResult: function(){return result;}
		};
	}
};

